]> dgit.raspbian.org Git - openjdk-25.git/commitdiff
[PATCH] 8337853: Remove SunLayoutEngineKey and SunLayoutEngineFactory and its cache...
authorPhil Race <prr@openjdk.org>
Mon, 23 Feb 2026 18:36:00 +0000 (18:36 +0000)
committerVladimir Petko <vladimir.petko@canonical.com>
Thu, 24 Sep 2026 07:52:19 +0000 (19:52 +1200)
From 569d18fbe51a036629337c38230ae4892365a228 Mon Sep 17 00:00:00 2001
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/openjdk-25/+bug/2155650
Bug: https://bugs.openjdk.org/browse/JDK-8337853
Origin: upstream, https://github.com/openjdk/jdk/commit/569d18fbe51a036629337c38230ae4892365a228

Reviewed-by: azvegint, dnguyen
Gbp-Pq: Name jdk-8337853.diff

src/java.desktop/share/classes/java/awt/Font.java
src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java
src/java.desktop/share/classes/sun/font/GlyphLayout.java
src/java.desktop/share/classes/sun/font/SunLayoutEngine.java

index 2da68fd8618000ea99df62bdd5d3449e419a9b09..beed47c251d39a3b9e71936c324729d282c1695b 100644 (file)
@@ -2709,7 +2709,7 @@ public class Font implements java.io.Serializable
                                          int limit,
                                          int flags) {
 
-        GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
+        GlyphLayout gl = GlyphLayout.get();
         StandardGlyphVector gv = gl.layout(this, frc, text,
                                            start, limit-start, flags, null);
         GlyphLayout.done(gl);
index 784035f4fe27d733764f53bb4983c3a23e639662..d7cf30ad69b6568cdae0f5f68e7deca6e95764d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -329,7 +329,7 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
     int start = source.getStart();
     int length = source.getLength();
 
-    GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
+    GlyphLayout gl = GlyphLayout.get();
     gv = gl.layout(font, frc, context, start, length, flags, null); // ??? use textsource
     GlyphLayout.done(gl);
 
index fe2a8bf25998ad4a10465b40922898b0f5988082..df42cce344ef1371c12b78b47b0963842213d3e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,7 +87,6 @@ public final class GlyphLayout {
     // cached glyph layout data for reuse
     private static volatile GlyphLayout cache;  // reusable
 
-    private LayoutEngineFactory _lef;  // set when get is called, unset when done is called
     private TextRecord _textRecord;    // the text we're working on, used by iterators
     private ScriptRun _scriptRuns;     // iterator over script runs
     private FontRunIterator _fontRuns; // iterator over physical fonts in a composite
@@ -100,91 +99,10 @@ public final class GlyphLayout {
     private int _typo_flags;
     private int _offset;
 
-    public static final class LayoutEngineKey {
-        private Font2D font;
-        private int script;
-        private int lang;
-
-        LayoutEngineKey() {
-        }
-
-        LayoutEngineKey(Font2D font, int script, int lang) {
-            init(font, script, lang);
-        }
-
-        void init(Font2D font, int script, int lang) {
-            this.font = font;
-            this.script = script;
-            this.lang = lang;
-        }
-
-        LayoutEngineKey copy() {
-            return new LayoutEngineKey(font, script, lang);
-        }
-
-        Font2D font() {
-            return font;
-        }
-
-        int script() {
-            return script;
-        }
-
-        int lang() {
-            return lang;
-        }
-
-        public boolean equals(Object rhs) {
-            if (this == rhs) return true;
-            if (rhs == null) return false;
-            try {
-                LayoutEngineKey that = (LayoutEngineKey)rhs;
-                return this.script == that.script &&
-                       this.lang == that.lang &&
-                       this.font.equals(that.font);
-            }
-            catch (ClassCastException e) {
-                return false;
-            }
-        }
-
-        public int hashCode() {
-            return script ^ lang ^ font.hashCode();
-        }
-    }
-
-    public static interface LayoutEngineFactory {
-        /**
-         * Given a font, script, and language, determine a layout engine to use.
-         */
-        public LayoutEngine getEngine(Font2D font, int script, int lang);
-
-        /**
-         * Given a key, determine a layout engine to use.
-         */
-        public LayoutEngine getEngine(LayoutEngineKey key);
-    }
-
-    public static interface LayoutEngine {
-        /**
-         * Given a strike descriptor, text, rtl flag, and starting point, append information about
-         * glyphs, positions, and character indices to the glyphvector data, and advance the point.
-         *
-         * If the GVData does not have room for the glyphs, throws an IndexOutOfBoundsException and
-         * leave pt and the gvdata unchanged.
-         */
-        public void layout(FontStrikeDesc sd, float[] mat, float ptSize, int gmask,
-                           int baseIndex, TextRecord text, int typo_flags, Point2D.Float pt, GVData data);
-    }
-
     /**
-     * Return a new instance of GlyphLayout, using the provided layout engine factory.
-     * If null, the system layout engine factory will be used.
+     * Return a possibly recycled instance of GlyphLayout
      */
-    public static GlyphLayout get(LayoutEngineFactory lef) {
-        if (lef == null) {
-            lef = SunLayoutEngine.instance();
-        }
+    public static GlyphLayout get() {
         GlyphLayout result = null;
         synchronized(GlyphLayout.class) {
             if (cache != null) {
@@ -195,7 +113,6 @@ public final class GlyphLayout {
         if (result == null) {
             result = new GlyphLayout();
         }
-        result._lef = lef;
         return result;
     }
 
@@ -204,7 +121,6 @@ public final class GlyphLayout {
      * of GlyphLayout objects.
      */
     public static void done(GlyphLayout gl) {
-        gl._lef = null;
         cache = gl; // object reference assignment is thread safe, it says here...
     }
 
@@ -398,8 +314,6 @@ public final class GlyphLayout {
             }
         }
 
-        int lang = -1; // default for now
-
         Font2D font2D = FontUtilities.getFont2D(font);
         if (font2D instanceof FontSubstitution) {
             font2D = ((FontSubstitution)font2D).getCompositeFont2D();
@@ -426,7 +340,7 @@ public final class GlyphLayout {
                     }
                     int gmask = _fontRuns.getGlyphMask();
                     int pos = _fontRuns.getPos();
-                    nextEngineRecord(start, pos, script, lang, pfont, gmask);
+                    nextEngineRecord(start, pos, script, pfont, gmask);
                     start = pos;
                 }
             }
@@ -435,7 +349,7 @@ public final class GlyphLayout {
             while (_scriptRuns.next()) {
                 int limit = _scriptRuns.getScriptLimit();
                 int script = _scriptRuns.getScriptCode();
-                nextEngineRecord(start, limit, script, lang, font2D, 0);
+                nextEngineRecord(start, limit, script, font2D, 0);
                 start = limit;
             }
         }
@@ -508,7 +422,7 @@ public final class GlyphLayout {
         this._gvdata.init(capacity);
     }
 
-    private void nextEngineRecord(int start, int limit, int script, int lang, Font2D font, int gmask) {
+    private void nextEngineRecord(int start, int limit, int script, Font2D font, int gmask) {
         EngineRecord er = null;
         if (_ercount == _erecords.size()) {
             er = new EngineRecord();
@@ -516,7 +430,7 @@ public final class GlyphLayout {
         } else {
             er = _erecords.get(_ercount);
         }
-        er.init(start, limit, font, script, lang, gmask);
+        er.init(start, limit, font, script, gmask);
         ++_ercount;
     }
 
@@ -627,18 +541,18 @@ public final class GlyphLayout {
         private int limit;
         private int gmask;
         private int eflags;
-        private LayoutEngineKey key;
-        private LayoutEngine engine;
+        private Font2D font;
+        private int script;
 
         EngineRecord() {
-            key = new LayoutEngineKey();
         }
 
-        void init(int start, int limit, Font2D font, int script, int lang, int gmask) {
+        void init(int start, int limit, Font2D font, int script, int gmask) {
             this.start = start;
             this.limit = limit;
+            this.font = font;
+            this.script = script;
             this.gmask = gmask;
-            this.key.init(font, script, lang);
             this.eflags = 0;
 
             // only request canonical substitution if we have combining marks
@@ -659,14 +573,12 @@ public final class GlyphLayout {
                     break;
                 }
             }
-
-            this.engine = _lef.getEngine(key); // flags?
         }
 
         void layout() {
             _textRecord.start = start;
             _textRecord.limit = limit;
-            engine.layout(_sd, _mat, ptSize, gmask, start - _offset, _textRecord,
+            SunLayoutEngine.layout(font, script, _sd, _mat, ptSize, gmask, start - _offset, _textRecord,
                           _typo_flags | eflags, _pt, _gvdata);
         }
     }
index f1d6de7d4bc5569da225261b91bb9c2bed9355f5..99d3987e5fd6738da506f5d8a2a5e03a5d8fe1cf 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,126 +37,22 @@ import sun.java2d.DisposerRecord;
 
 import java.awt.geom.Point2D;
 import java.lang.foreign.MemorySegment;
-import java.lang.ref.SoftReference;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.WeakHashMap;
 
-/*
- * different ways to do this
- * 1) each physical font2d keeps a hashtable mapping scripts to layout
- * engines, we query and fill this cache.
- * 2) we keep a mapping independent of font using the key Most likely
- * few fonts will be used, so option 2 seems better
- *
- * Once we know which engine to use for a font, we always know, so we
- * shouldn't have to recheck each time we do layout.  So the cache is
- * ok.
- *
- * Should we reuse engines?  We could instantiate an engine for each
- * font/script pair.  The engine would hold onto the table(s) from the
- * font that it needs.  If we have multiple threads using the same
- * engine, we still need to keep the state separate, so the native
- * engines would still need to be allocated for each call, since they
- * keep their state in themselves.  If they used the passed-in GVData
- * arrays directly (with some checks for space) then since each GVData
- * is different per thread, we could reuse the layout engines.  This
- * still requires a separate layout engine per font, because of the
- * table state in the engine.  If we pushed that out too and passed it
- * in with the native call as well, we'd be ok if the layout engines
- * keep all their process state on the stack, but I don't know if this
- * is true.  Then we'd basically just be down to an engine index which
- * we pass into native and then invoke the engine code (now a
- * procedure call, not an object invocation) based on a switch on the
- * index.  There would be only half a dozen engine objects then, not
- * potentially half a dozen per font.  But we'd have to stack-allocate
- * some state that included the pointer to the required font tables.
- *
- * Seems for now that the way to do things is to come in with a
- * selector and the font.  The selector indicates which engine to use,
- * the engine is stack allocated and initialized with the required
- * font tables (the selector indicates which).  Then layout is called,
- * the contents are copied (or not), and the stack is destroyed on
- * exit. So the association is between the font/script (layout engine
- * desc) and one of a few permanent engine objects, which are
- * handed the key when they need to process something.  In the native
- * case, the engine holds an index, and just passes it together with
- * the key info down to native.  Some default cases are the 'default
- * layout' case that just runs the c2gmapper, this stays in java and
- * just uses the mapper from the font/strike.  Another default case
- * might be the unicode arabic shaper, since this doesn't care about
- * the font (or script or lang?) it wouldn't need to extract this
- * data.  It could be (yikes) ported back to java even to avoid
- * upcalls to check if the font supports a particular unicode
- * character.
- *
- * I'd expect that the majority of scripts use the default mapper for
- * a particular font.  Loading the hashtable with 40 or so keys 30+ of
- * which all map to the same object is unfortunate.  It might be worth
- * instead having a per-font list of 'scripts with non-default
- * engines', e.g. the factory has a hashtable mapping fonts to 'script
- * lists' (the factory has this since the design potentially has other
- * factories, though I admit there's no client for this yet and no
- * public api) and then the script list is queried for the script in
- * question.  it can be preloaded at creation time with all the
- * scripts that don't have default engines-- either a list or a hash
- * table, so a null return from the table means 'default' and not 'i
- * don't know yet'.
- *
- * On the other hand, in most all cases the number of unique
- * script/font combinations will be small, so a flat hashtable should
- * suffice.
- * */
-public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory {
+public final class SunLayoutEngine {
+
     static {
         FontManagerNativeLibrary.load();
     }
 
-    private LayoutEngineKey key;
-
-    private static LayoutEngineFactory instance;
-
-    public static LayoutEngineFactory instance() {
-        if (instance == null) {
-            instance = new SunLayoutEngine();
-        }
-        return instance;
-    }
-
     private SunLayoutEngine() {
-        // actually a factory, key is null so layout cannot be called on it
-    }
-
-    public LayoutEngine getEngine(Font2D font, int script, int lang) {
-        return getEngine(new LayoutEngineKey(font, script, lang));
-    }
-
-  // !!! don't need this unless we have more than one sun layout engine...
-    public LayoutEngine getEngine(LayoutEngineKey key) {
-        ConcurrentHashMap<LayoutEngineKey, LayoutEngine> cache = cacheref.get();
-        if (cache == null) {
-            cache = new ConcurrentHashMap<>();
-            cacheref = new SoftReference<>(cache);
-        }
-
-        LayoutEngine e = cache.get(key);
-        if (e == null) {
-            LayoutEngineKey copy = key.copy();
-            e = new SunLayoutEngine(copy);
-            cache.put(copy, e);
-        }
-        return e;
-    }
-    private SoftReference<ConcurrentHashMap<LayoutEngineKey, LayoutEngine>> cacheref =
-        new SoftReference<>(null);
-
-    private SunLayoutEngine(LayoutEngineKey key) {
-        this.key = key;
     }
 
     private static final WeakHashMap<Font2D, FaceRef> facePtr =
             new WeakHashMap<>();
 
-    private long getFacePtr(Font2D font2D) {
+    private static long getFacePtr(Font2D font2D) {
         FaceRef ref;
         synchronized (facePtr) {
             ref = facePtr.computeIfAbsent(font2D, FaceRef::new);
@@ -170,17 +67,16 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
 
     }
 
-    public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
+    public static void layout(Font2D font, int script, FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
                        int baseIndex, TextRecord tr, int typo_flags,
                        Point2D.Float pt, GVData data) {
 
-        Font2D font = key.font();
         FontStrike strike = font.getStrike(desc);
         if (useFFM) {
             MemorySegment face = HBShaper.getFace(font);
             if (face != null) {
                 HBShaper.shape(font, strike, ptSize, mat, face,
-                        tr.text, data, key.script(),
+                        tr.text, data, script,
                         tr.start, tr.limit, baseIndex, pt,
                         typo_flags, gmask);
             }
@@ -188,7 +84,7 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
             long pFace = getFacePtr(font);
             if (pFace != 0) {
                 shape(font, strike, ptSize, mat, pFace,
-                    tr.text, data, key.script(),
+                    tr.text, data, script,
                     tr.start, tr.limit, baseIndex, pt,
                     typo_flags, gmask);
             }